package org.linlinjava.litemall.admin.job;

import java.math.BigDecimal;
import java.time.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.beans.Constants;
import org.linlinjava.litemall.core.config.DynamicTimeZoneConfiguration;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.notify.PosPushSender;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.CouponUserConstant;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 订单工作
 * 检测订单状态
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Component
public class OrderJob {
    /**
     * 日志记录器
     */
    private final Log logger = LogFactory.getLog(OrderJob.class);

    /**
     * 订单商品服务
     */
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    /**
     * 订单服务
     */
    @Autowired
    private LitemallOrderService orderService;
    /**
     * 优惠券用户服务
     */
    @Autowired
    private LitemallCouponUserService couponUserService;
    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;
    /**
     * 店服务
     */
    @Autowired
    private LitemallShopService shopService;
    /**
     * 完整日志服务
     */
    @Autowired
    private LitemallIntegralLogService integralLogService;
    /**
     * pos推发送方
     */
    @Autowired
    private PosPushSender posPushSender;
    /**
     * 注意助手
     */
    @Autowired
    private NoticeHelper noticeHelper;

    @Autowired
    private LitemallShopService litemallShopService;

    private DynamicTimeZoneConfiguration dynamicTimeZoneConfiguration = new DynamicTimeZoneConfiguration();
    /**
     * 检查订单未付
     * 自动取消订单
     * <p>
     * 定时检查订单未付款情况，如果超时 LITEMALL_ORDER_UNPAID 分钟则自动取消订单
     * 定时时间是每次相隔半个小时。
     * <p>
     * TODO
     * 注意，因为是相隔半小时检查，因此导致订单真正超时时间是 [LITEMALL_ORDER_UNPAID, 30 + LITEMALL_ORDER_UNPAID]
     */
    @Scheduled(fixedDelay = 30 * 60 * 1000)
    @Transactional(rollbackFor = Exception.class)
    public void checkOrderUnpaid() {
        logger.info("系统开启任务检查订单是否已经超期自动取消订单");

        //查询超过30分钟的未付款订单
        List<LitemallOrder> orderList = orderService.queryOverTime(Constants.ORDER_STATUS_UNPAID, 30);
        if (!CollectionUtils.isEmpty(orderList)) {
            for (LitemallOrder litemallOrder : orderList) {
                try {
                    // 设置订单已取消状态
                    litemallOrder.setOrderStatus(Constants.STATUS_AUTO_CANCEL);
                    litemallOrder.setEndTime(LocalDateTime.now());
                    orderService.updateById(litemallOrder);
                    logger.info("订单 ID" + litemallOrder.getId() + " 已经超期自动取消订单");

                    // 返还优惠券
//                    Integer couponId
                    List<LitemallCouponUser> couponUsers = couponUserService.queryByOrderId(litemallOrder.getId());
                    if (couponUsers != null && couponUsers.size() > 0) {
                        for (LitemallCouponUser couponUser : couponUsers) {
                            couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
                            couponUser.setUsedTime(null);
                            couponUser.setOrderId(null);
                            couponUserService.recover(couponUser);
                        }
                    }

                    // 推送pos
                    posPushSender.pushPos(litemallOrder.getShopId(), Constants.ORDER_PUSH_TYPE_CANCEL, null);
                } catch (Exception e) {
                    logger.info("订单 ID" + litemallOrder.getId() + " 超期自动取消订单失败");
                }
            }
        }

        /**
         List<LitemallOrder> orderList = orderService.queryUnpaid(SystemConfig.getOrderUnpaid());
         for (LitemallOrder order : orderList) {
         // 设置订单已取消状态
         order.setOrderStatus(OrderUtil.STATUS_AUTO_CANCEL);
         order.setEndTime(LocalDateTime.now());
         if (orderService.updateWithOptimisticLocker(order) == 0) {
         throw new RuntimeException("更新数据已失效");
         }

         // 商品货品数量增加
         Integer orderId = order.getId();
         List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
         for (LitemallOrderGoods orderGoods : orderGoodsList) {
         Integer productId = orderGoods.getProductId();
         Short number = orderGoods.getNumber();
         if (productService.addStock(productId, number) == 0) {
         throw new RuntimeException("商品货品库存增加失败");
         }
         }

         // 返还优惠券
         List<LitemallCouponUser> couponUsers = couponUserService.queryByOrderId(orderId);
         if(couponUsers != null && couponUsers.size() > 0){
         for(LitemallCouponUser couponUser : couponUsers){
         couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
         couponUser.setUsedTime(null);
         couponUser.setOrderId(null);
         couponUserService.recover(couponUser);
         }
         }

            // 如果使用了积分，更新积分
            if (order.getIntegralPrice() != null && order.getIntegralPrice().compareTo(new BigDecimal(0.00)) > 0) {
                String config = SystemConfig.getConfig(SystemConfig.LITEMALL_INTEGRAL_AMOUNT);
                if(!StringUtils.isEmpty(config)){
                    try{
                        double v = Double.parseDouble(config);
                        LitemallUser user = userService.findById(order.getUserId());
                        LitemallUser update = new LitemallUser();
                        update.setId(order.getUserId());
                        update.setPoints(user.getPoints().add(order.getIntegralPrice().divide(new BigDecimal(v))));
                        userService.updateById(update);
                    }catch (Exception e){
                        logger.info("取消订单，返还积分失败");
                        logger.info(e);
                    }
                }

            }
            logger.info("订单 ID" + order.getId() + " 已经超期自动取消订单");
        }
        */
    }

    /**
     * 检查顺序unconfirm
     * 自动确认订单
     * <p>
     * 定时检查订单未确认情况，如果超时 LITEMALL_ORDER_UNCONFIRM 天则自动确认订单
     * 定时时间是每天凌晨3点。
     * <p>
     * TODO
     * 注意，因为是相隔一天检查，因此导致订单真正超时时间是 [LITEMALL_ORDER_UNCONFIRM, 1 + LITEMALL_ORDER_UNCONFIRM]
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void checkOrderUnconfirm() {
        logger.info("系统开启任务检查订单是否已经超期自动确认收货");

        List<LitemallOrder> orderList = orderService.queryUnconfirm(SystemConfig.getOrderUnconfirm());
        for (LitemallOrder order : orderList) {

            // 设置订单已取消状态
            order.setOrderStatus(OrderUtil.STATUS_AUTO_CONFIRM);
            order.setConfirmTime(LocalDateTime.now());
            if (orderService.updateWithOptimisticLocker(order) == 0) {
                logger.info("订单 ID=" + order.getId() + " 数据已经更新，放弃自动确认收货");
            } else {
                logger.info("订单 ID=" + order.getId() + " 已经超期自动确认收货");
            }
        }
    }

    /**
     * 检查订单评论
     * 可评价订单商品超期
     * <p>
     * 定时检查订单商品评价情况，如果确认商品超时 LITEMALL_ORDER_COMMENT 天则取消可评价状态
     * 定时时间是每天凌晨4点。
     * <p>
     * TODO
     * 注意，因为是相隔一天检查，因此导致订单真正超时时间是 [LITEMALL_ORDER_COMMENT, 1 + LITEMALL_ORDER_COMMENT]
     */
    @Scheduled(cron = "0 0 4 * * ?")
    public void checkOrderComment() {
        logger.info("系统开启任务检查订单是否已经超期未评价");

        List<LitemallOrder> orderList = orderService.queryComment(SystemConfig.getOrderComment());
        for (LitemallOrder order : orderList) {
            order.setComments((short) 0);
            orderService.updateWithOptimisticLocker(order);

            List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(order.getId());
            for (LitemallOrderGoods orderGoods : orderGoodsList) {
                orderGoods.setComment(-1);
                orderGoodsService.updateById(orderGoods);
            }
        }
    }

    /**
     * 检查顺序接
     * 自动完成订单
     * <p>
     * 定时检查订单已取餐情况，如果超时30分钟则自动完成订单
     * 定时时间是每次相隔1分钟。
     * <p>
     */
    @Scheduled(fixedDelay = 1 * 60 * 1000)
    @Transactional(rollbackFor = Exception.class)
    public void checkOrderPickUp() {
        logger.info("系统开启任务检查已取餐的订单是否已经超期，自动完成订单");
        
        //查询超过30分钟的未付款订单
        List<LitemallOrder> orderList = orderService.queryOverTime(Constants.ORDER_STATUS_PICKUP, 30);
        if(!CollectionUtils.isEmpty(orderList)) {
        	for (LitemallOrder litemallOrder : orderList) {
        		try {
        			// 设置订单已完成状态
        			litemallOrder.setOrderStatus(Constants.ORDER_STATUS_FINISHED);
                    litemallOrder.setCompleteTime(LocalDateTime.now());
        			LocalDateTime endTime = LocalDateTime.now();
        			litemallOrder.setEndTime(endTime);
        			litemallOrder.setEndYear(endTime.getYear());
        			litemallOrder.setEndMonth(endTime.getMonth().getValue());
        			orderService.updateById(litemallOrder);
        			logger.info("订单 ID" + litemallOrder.getId() + " 已经超期自动完成订单");
        			
        			Integer shopId = litemallOrder.getShopId();
        	    	
        	    	//增加积分
        	    	Integer userId = litemallOrder.getUserId();
        	    	if(null != userId) {
        	    		LitemallUser user = userService.findById(userId);
        	    		if(user != null){
        	    			//获取积分系数配置
        	    			String config = SystemConfig.getConfig(SystemConfig.LITEMALL_INTEGRAL);
        	    			BigDecimal changePoints = litemallOrder.getActualPrice().multiply(new BigDecimal(config));
        	    			BigDecimal points = user.getPoints().add(changePoints);
        	    			
        	    			//添加积分记录
        	    			LitemallIntegralLog log = new LitemallIntegralLog();
        	    			log.setUserId(userId);
        	    			log.setType(Constants.INTEGRAL_LOG_TYPE_ADD);
        	    			log.setPoints(points);
        	    			log.setChangePoints(changePoints);
        	    			integralLogService.add(log);
        	    			
        	    			//修改积分
        	    			LitemallUser update = new LitemallUser();
        	    			update.setId(userId);
        	    			update.setPoints(points);
        	    			userService.updateById(update);
        	    		}
        	    	}
        			// 推送pos
        	    	posPushSender.pushAll(shopId, Constants.ORDER_PUSH_TYPE_DONE, null);
				} catch (Exception e) {
					logger.info("订单 ID" + litemallOrder.getId() + " 超期自动完成订单失败");
				}
        	}
        }

       
    }

    /**
     * 重置serinal数量
     * 流水号更新
     * <p>
     */
    @Scheduled(cron = "0 0 0 * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void resetSerinalNumber() {
        logger.info("新的一天重置流水号");

        //查询所有门店
       List<LitemallShop> shops = shopService.all();
       LitemallOrder updater = new LitemallOrder();

       shops.stream().forEach(shop -> {
          List<LitemallOrder> orders = orderService.queryLastOrder(shop.getId());
          LitemallOrder lastOrder = orders.get(0);
          updater.setId(lastOrder.getId());
          updater.setSerinalNumber(0);
          orderService.updateById(updater);
       });
    }

    /**
     * 删除新或挂起状态
     */
    @Scheduled(cron = "0 0 3 * * ?")
    public void deleteStatusNewOrHang() {
         List<Short> status =   new ArrayList<>(Arrays.asList(new Short[]{Constants.ORDER_STATUS_NEW, Constants.ORDER_STATUS_HANG}));
        List<LitemallOrder> orders = orderService.queryByOrderStatus(null,status,null);
        if(orders.size() > 0){
            for (int i = 0; i < orders.size(); i++) {
                LitemallOrder order = new LitemallOrder();
                order.setId(orders.get(i).getId());
                order.setDeleted(true);
                orderService.updateById(order);
            }
        }

    }

    /**
     * 过营业时间后 自动完成订单 更新订单时间
     * 四小时执行一次
     */
    @Scheduled(cron = "0 0 */4 * * ?")
    public void checkOrderBusinessTime(){
        CompletableFuture.runAsync(() -> {
            //所有门店
            List<LitemallShop> litemallShops = litemallShopService.all();
            litemallShops.forEach(shop -> {
                Short status = shop.getStatus();
                if(status == 2){
                    //遍历所有门店，将歇业的门店的待发货订单都改为已完成订单
                    orderGoodsService.makeOrderStateFinish(Constants.ORDER_STATUS_ONGOING, shop.getId());
                }
            });
        });
    }

//    /**
//     * 强制补偿
//     * 订单状态改为已完成
//     * 一小时执行一次
//     */
//    @Scheduled(cron = "0 0 */1 * * ?")
//    public void forceCompensate(){
//        CompletableFuture.runAsync(() -> {
//            //所有门店
//            List<LitemallShop> litemallShops = litemallShopService.all();
//            litemallShops.forEach(shop -> {
//                //遍历所有门店，将所有的门店的待制作的订单都改为已完成
//                orderGoodsService.modifyOrderMakeState(Constants.ORDER_STATUS_ONGOING, shop.getId());
//            });
//        });
//    }


}
